const { exec } = require('child_process');
const util = require('util');
const path = require('path');

const execPromise = util.promisify(exec);

const REMOTE_USER = 'root';
const REMOTE_HOST = '8.134.250.251';
const REMOTE_PATH = '/data/nginx/diet-back';
const LOCAL_PROJECT_PATH = path.resolve(__dirname, '../');
const FILES_TO_UPLOAD = ['dist', 'package.json', '.env'];

const BUILD_COMMAND = 'npm run build';
const PM2_APP_NAME = 'diet-back';

async function buildCommand() {
  console.log('🛠️ Build 开始执行');
  await execPromise(BUILD_COMMAND, { cwd: LOCAL_PROJECT_PATH });
  console.log('✅ Build 执行完成\n');
}

async function uploadFiles() {
  console.log('🚀 上传文件中...');

  const uploadPromises = FILES_TO_UPLOAD.map(async (item) => {
    const sourcePath = path.join(LOCAL_PROJECT_PATH, item);
    const targetPath = `${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/`;

    console.log(`📂 上传 ${sourcePath} 到 ${targetPath}`);
    await execPromise(`rsync -avz --delete ${sourcePath} ${targetPath}`);
  });

  await Promise.all(uploadPromises);

  console.log('✅ 文件上传完成\n');
}

async function remoteInstallAndStart() {
  console.log('📦 正在服务器安装启动依赖');

  const remoteCommand = [
    `source ~/.zshrc || true`, // 加载 zsh 配置（即使文件不存在也继续），ssh 交互不会加载环境变量
    `nvm use 20`,
    `mkdir -p ${REMOTE_PATH}`,
    `cd ${REMOTE_PATH}`,
    `pnpm install --prod`,
    `pm2 list | grep -q '${PM2_APP_NAME}' && pm2 restart '${PM2_APP_NAME}' || pm2 start dist/main.js --name '${PM2_APP_NAME}' --max-restarts 20`,
  ].join(' && ');

  const sshCommand = `ssh ${REMOTE_USER}@${REMOTE_HOST} '${remoteCommand}'`;

  await execPromise(sshCommand);

  console.log('✅ 服务器端安装 & 启动完成\n');
}

async function main() {
  console.log('====== 📤 开始部署任务 ======\n');

  await buildCommand();
  await uploadFiles();
  await remoteInstallAndStart();

  console.log('====== ✅ 一键部署完成 ======');
  console.log(new Date().toLocaleString('zh-cn'), '\n');
  console.log('\x1b[32m%s\x1b[0m', `项目已部署并运行在服务器：${REMOTE_PATH}`);
}

main();
